home *** CD-ROM | disk | FTP | other *** search
/ Die Speccy' 97 / Die Speccy' 97.iso / amiga_system / the_aminet / comm / fido / smartpoll.lha / SmartPoll.rexx < prev   
OS/2 REXX Batch file  |  1995-09-15  |  17KB  |  675 lines

  1. /* $VER:SmartPoll.rexx 1.3 (31.8.95)
  2.  *
  3.  * Advanced poll script, written for points. Can poll several bosses (with
  4.  * multiple lines). Also includes a "TrapPoll clone", for easy handling of
  5.  * crash mail/filerequests etc.
  6.  *
  7.  * See SmartPoll.Man for more information.
  8.  */
  9.  
  10. OPTIONS RESULTS
  11. PARSE ARG ConfigName
  12. SIGNAL ON BREAK_C
  13. SIGNAL ON ERROR
  14. SIGNAL ON HALT
  15.  
  16. /* Some useful constants */
  17. Cr  = '0d'x
  18. Lf  = '0a'x
  19.  
  20. /* Get some needed resources */
  21. IF ~Show( 'Libraries', 'rexxreqtools.library' ) THEN DO
  22.     CALL AddLib( 'rexxreqtools.library', 0, -30 )
  23. END
  24.  
  25. ConOpen = 0    /* True if 'Con' file is open */
  26. TDStarted = 0    /* True if this script started TrapDoor */
  27.  
  28. IF ConfigName = '' | ConfigName = 'CONFIGNAME' THEN DO
  29.     IF ~Exists( 'Mail:SmartPoll.cfg' ) & Exists( 'Mail:Poll.cfg' ) THEN DO
  30.         ConfigName = 'Mail:Poll.cfg'
  31.     END
  32.     ELSE DO
  33.         ConfigName = 'Mail:Poll.cfg'
  34.     END
  35. END
  36.  
  37. /* Date to use when comparing for polling */
  38. StartDate = Date( 'Internal' )
  39.  
  40. /* Get the configuration */
  41. IF ~ReadConfig() THEN DO
  42.     RETURN( 20 )
  43. END
  44.  
  45. /* No need to start TrapDoor if there are no nodes */
  46. IF Nodes = 0 THEN DO
  47.     SAY 'No nodes found in "'ConfigName'"'
  48.     RETURN( 10 )
  49. END
  50.  
  51. /* Read in the old poll dates from Mail:Poll.data */
  52. CALL ReadData
  53.  
  54. /* Add any nodes from the outbound drawer */
  55. CALL ScanOutBound
  56.  
  57. DoPoll = 0
  58.  
  59. /* Check if we should poll any node */
  60. DO I = 1 FOR Nodes
  61.     IF Node.I.ExtraPoll | ( StartDate - Node.I.Poll >= Node.I.Days ) THEN DO
  62.         DoPoll = 1        /* Node(s) needs polling */
  63.     END
  64.     ELSE DO
  65.         Node.I.Polled = 1    /* Node not due for polling */
  66.     END
  67. END
  68.  
  69. IF ~DoPoll THEN DO
  70.     SAY 'No node(s) need polling'
  71.     RETURN( 0 )
  72. END
  73.  
  74. /* And now start TrapDoor, if needed/possible */
  75. IF ~StartTD() THEN DO
  76.     RETURN( 20 )
  77. END
  78.  
  79. ADDRESS VALUE RexxName
  80.  
  81. /* The main loop. Iterate until all nodes have been polled */
  82. IF Open( 'Con', ConsoleName ) THEN DO
  83.     ConOpen = 1
  84.     NodesLeft = Nodes
  85.  
  86.     DO UNTIL NodesLeft < 1
  87.         NodesLeft = Nodes
  88.  
  89.         /* Iterate through all nodes */
  90.         DO I = 1 FOR Nodes
  91.             /* Only poll nodes that should be polled */
  92.             IF Node.I.Polled THEN DO
  93.                 NodesLeft = NodesLeft - 1
  94.                 ITERATE I
  95.             END
  96.  
  97.             /* Handle "custom" phone numbers */
  98.             IF Node.I.Boss ~= '' THEN DO
  99.                 'Boss 'Node.I.Boss
  100.                 CALL WriteCh( 'Con', 'Calling 'Node.I.Boss', number: ' )
  101.             END
  102.             ELSE DO
  103.                 CALL WriteCh( 'Con', 'Calling: ' )
  104.             END
  105.  
  106.             /* Handle custom passwords */
  107.             IF Node.I.Password ~= '' THEN DO
  108.                 'Password 'Node.I.Password
  109.             END
  110.  
  111.             /* Iterate through all numbers for the current node */
  112.             DO J = 1 FOR Node.I.0
  113.                 CALL WriteCh( 'Con', Node.I.J'...' )
  114.                 'Call ' Node.I.J
  115.                 'Status X'
  116.  
  117.                 /* Handle all kinds of return codes */
  118.                 SELECT
  119.                     WHEN Result = 0 THEN DO    /* The call was successfull */
  120.                         IF Node.I.ExtraPoll THEN DO
  121.                             Node.I.ExtraPoll = 0
  122.                         END
  123.                         ELSE DO
  124.                             Node.I.Poll = StartDate
  125.                         END
  126.  
  127.  
  128.                         /* Indicate completion */
  129.                         CALL WriteCh( 'Con', 'Transfer complete' )
  130.                         Node.I.Polled = 1
  131.                     END
  132.                     WHEN Result = 5 THEN DO    /* User break */
  133.                         rtResult = 0
  134.  
  135.                         IF DoAsk THEN DO
  136.                             CALL rtEZRequest( 'Do you want to continue polling this node?', '_Yes|_No', 'SmartPoll request', 'RT_PubScrName='PubScreen )
  137.                         END
  138.  
  139.                         IF rtResult = 0 THEN DO
  140.                             Node.I.Polled = 1
  141.                         END
  142.                     END
  143.                     WHEN Result = 13 | Result = 15 THEN DO    /* Undialable node */
  144.                         CALL WriteCh( 'Con', 'This node can''t be polled (undialable node)' )
  145.                         Node.I.Polled = 1
  146.                     END
  147.                     WHEN Result = 14 THEN DO    /* Accounting limit reached */
  148.                         CALL WriteCh( 'Con', 'Accounting limit reached' )
  149.                         Node.I.Polles = 1
  150.                     END
  151.                     WHEN Result = 18 THEN DO    /* Ignore BUSY messages */
  152.                         NOP
  153.                     END
  154.                     WHEN Result = 11 | Result = 22 THEN DO    /* No answer */
  155.                         rtResult = 0
  156.  
  157.                         IF DoAsk THEN DO
  158.                             CALL rtEZRequest( 'No answer from this node.'Lf'Do you want to continue polling this node?', '_Yes| _No ', 'SmartPoll request', 'RT_PubScrName='PubScreen' RTEZ_Flags=EZREQF_CenterText' )
  159.                         END
  160.  
  161.                         IF rtResult = 0 THEN DO
  162.                             Node.I.Polled = 1
  163.                         END
  164.                     END
  165.                     OTHERWISE DO    /* Other kind of errors */
  166.                         Node.I.Errors = Node.I.Errors + 1
  167.  
  168.                         IF Node.I.Errors >= ErrorLimit THEN DO
  169.                             rtResult = 0
  170.  
  171.                             IF DoAsk THEN DO
  172.                                 CALL rtEZRequest( 'Error limit ('ErrorLimit') reached.'Lf'Do you want to continue polling this node?', '_Keep polling|_Clear error count|_Stop polling', 'SmartPoll request', 'RT_PubScrName='PubScreen' RTEZ_Flags=EZREQF_CenterText' )
  173.                             END
  174.  
  175.                             SELECT
  176.                                 WHEN rtResult = 0 THEN DO
  177.                                     Node.I.Polled = 1
  178.                                 END
  179.                                 WHEN rtResult = 2 THEN DO
  180.                                     Node.I.Errors = 0
  181.                                 END
  182.                                 OTHERWISE DO
  183.                                     NOP
  184.                                 END
  185.                             END
  186.                         END
  187.                     END
  188.                 END
  189.  
  190.                 IF Node.I.Polled THEN DO
  191.                     NodesLeft = NodesLeft - 1
  192.                     LEAVE J
  193.                 END
  194.             END
  195.  
  196.             CALL WriteCh( 'Con', Lf )
  197.         END
  198.  
  199.         IF NodesLeft > 0 THEN DO    /* And now for the redial delay */
  200.             CALL WriteCh( 'Con', ' 'RedialDelay' secs... 'Cr )
  201.  
  202.             DO I = RedialDelay - 1 BY -1 FOR RedialDelay
  203.                 CALL Delay( 50 )
  204.                 CALL WriteCh( 'Con', ' 'I' secs... 'Cr )
  205.             END
  206.         END
  207.  
  208.         CALL WriteCh( 'Con', Lf )
  209.     END
  210. END
  211. ELSE DO
  212.     SAY "Couldn't open console window"
  213. END
  214.  
  215. SaveData:
  216.  
  217. IF ConOpen THEN DO
  218.     CALL Close( 'Con' )
  219. END
  220.  
  221. /* Write back the poll dates, so we know which nodes that need polling next time. */
  222. IF Open( 'Data', 'Mail:SmartPoll.data', 'W' ) THEN DO
  223.     DO I = 1 FOR Nodes
  224.         IF Node.I.Save THEN DO
  225.             CALL WriteLn( 'Data', Node.I.Poll )
  226.         END
  227.     END
  228.  
  229.     CALL Close( 'Data' )
  230. END
  231.  
  232. /* Now tell TrapDoor to quit, in case we started it */
  233. IF TDStarted THEN DO
  234.     ADDRESS VALUE RexxName
  235.     'Quit'
  236. END
  237.  
  238. RETURN
  239.  
  240.  
  241. /* Scan outbound directory, asking if nodes should be added, and add those
  242.  * that should be added. Set the Save stem to 0 for these nodes, to prevent the
  243.  * information from being written to the Poll.data file. If a boss isn't due
  244.  * for call, but there is a file for it, then the user will be asked if the
  245.  * boss is to be polled anyway.
  246.  */
  247. ScanOutbound:
  248.  
  249.     IF Crash | Direct | Normal | Request THEN DO
  250.         /* Make sure we have the needed resources */
  251.         IF ~Show( 'Libraries', 'traplist.library' ) THEN DO
  252.             CALL AddLib( 'traplist.library', -5, -30 )
  253.         END
  254.  
  255.         IF ~Show( 'Libraries', 'rexxsupport.library' ) THEN DO
  256.             CALL AddLib( 'rexxsupport.library', 0, -30 )
  257.         END
  258.  
  259.         /* The files TrapDoor expect usually doesn't have any spaces in them.. :) */
  260.         Files = ShowDir( Outbound, 'File' )
  261.  
  262.         /* And now process all files */
  263.         DO J = 1 FOR Words( Files )
  264.             File = Word( Files, J )
  265.             FileInfo = StateF( File )
  266.             PARSE VAR FileInfo Type Size ' ' .
  267.  
  268.             /* Skip empty files and dirs */
  269.             IF Size = 0 | Type = 'DIR' THEN DO
  270.                 ITERATE J
  271.             END
  272.  
  273.             Ext = Upper( Right( File, 4 ) )
  274.  
  275.             SELECT
  276.                 WHEN Ext = '.CLO' | Ext = '.CUT' THEN DO
  277.                     Type = 'crash'
  278.                 END
  279.                 WHEN Ext = '.DLO' | Ext = '.DUT' THEN DO
  280.                     Type = 'direct'
  281.                 END
  282.                 WHEN Ext = '.FLO' | Ext = '.OUT' THEN DO
  283.                     Type = 'normal'
  284.                 END
  285.                 WHEN Ext = '.REQ' THEN DO
  286.                     Type = 'request'
  287.                 END
  288.                 OTHERWISE DO    /* Ignore unknown files */
  289.                     ITERATE J
  290.                 END
  291.             END
  292.  
  293.             /* Only handle configured types */
  294.             IF ( Crash   & Type = 'crash'  ) | ( Direct  & Type = 'direct' ) | ,
  295.                ( Normal  & Type = 'normal' ) | ( Request & Type = 'request' ) THEN DO
  296.                 PARSE VAR File Zone '.' Net '.' Node '.' Point '.' .
  297.                 NodeNum = Zone':'Net'/'Node'.'Point
  298.                 BossNum = 0
  299.  
  300.                 /* Skip nodes that should be ignored (e.g. AmiGate packets) */
  301.                 DO I = 1 FOR Ignores
  302.                     IF Ignore.I = NodeNum THEN DO
  303.                         ITERATE J
  304.                     END
  305.                 END
  306.  
  307.                 /* Rename NodeNum if it is an AKA */
  308.                 DO I = 1 FOR Akas
  309.                     IF Aka.I.Also = NodeNum THEN DO
  310.                         NodeNum = Aka.I.Node
  311.                         LEAVE I
  312.                     END
  313.                 END
  314.  
  315.                 /* Check if this is a boss that is about to be called.
  316.                  * No need to ask the user for a poll in that case.
  317.                  */
  318.                 DO I = 1 FOR Nodes
  319.                     IF ( Node.I.Boss ~= '' & Node.I.Boss = NodeNum ) |,
  320.                        ( Node.I.1 = NodeNum ) THEN DO
  321.                         IF StartDate - Node.I.Poll < Node.I.Days THEN DO
  322.                             BossNum = I
  323.                         END
  324.                         ELSE DO
  325.                             ITERATE J
  326.                         END
  327.                     END
  328.                 END
  329.  
  330.                 /* Get some information about this node */
  331.                 NodeName = FindNode( NodeNum, 'System' )
  332.                 NodeCity = FindNode( NodeNum, 'Location' )
  333.                 NodePassword = FindNode( NodeNum, 'Password' )
  334.  
  335.                 IF SubStr( NodeName, 1, 1 ) = '0' | SubStr( NodeCity, 1, ) = 0 THEN DO
  336.                     IF DoAsk THEN DO
  337.                         CALL rtEZRequest( "Couldn't find node "NodeNum" in current nodelist", ' Ok ', 'Poll information', 'RT_PubScrName='PubScreen )
  338.                     END
  339.  
  340.                     ITERATE J
  341.                 END
  342.  
  343.                 NodeName = SubStr( NodeName, 3 )
  344.                 NodeCity = SubStr( NodeCity, 3 )
  345.  
  346.                 IF SubStr( NodePassword, 1, 1 ) = '0' THEN DO
  347.                     NodePassword = ''
  348.                 END
  349.                 ELSE DO
  350.                     NodePassword = SubStr( NodePassword, 3 )
  351.                 END
  352.  
  353.                 IF DoAsk THEN DO
  354.                     IF BossNum > 0 THEN DO
  355.                         InDays = Node.BossNum.Days - ( StartDate - Node.BossNum.Poll )
  356.                         BossMsg = ','Lf'a boss due for polling in 'InDays' day(s)'
  357.                         Gadgets = '_Add|_Skip'
  358.                     END
  359.                     ELSE DO
  360.                         BossMsg = ''
  361.                         Gadgets = '_Add|_Delete|_Skip'
  362.                     END
  363.  
  364.                     CALL rtEZRequest( 'Add node 'NodeNum||Lf'('type' file to 'NodeName' in 'NodeCity||BossMsg')'Lf'to the poll list?', Gadgets, 'Poll request', 'RTEZ_Flags=EZREQF_CenterText RT_PubScrName='PubScreen )
  365.                 END
  366.                 ELSE DO
  367.                     rtResult = 1
  368.                 END
  369.  
  370.                 IF rtResult = 2 THEN DO
  371.                     CALL rtEZRequest( 'Really delete "'File'"'Lf'('type' file to'NodeName' in 'NodeCity')?', ' _Ok |_Cancel', 'Poll request', 'RT_PubScrName='PubScreen' RTEZ_Flags=EZREQF_CenterText RTEZ_DefaultResponse=0' )
  372.  
  373.                     IF rtResult = 1 THEN DO
  374.                         Delete( Outbound||File )
  375.  
  376.                         /* We need to handle the cases with several files.
  377.                          * This does not handle "normal" mail bundles,
  378.                          * but then again, for "normal" mail, the delete
  379.                          * option is not available in the requester above! :)
  380.                          */
  381.                         Index = Index( '.CLO.CUT.DLO.DUT', Ext )
  382.  
  383.                         IF Index > 0 THEN DO
  384.                             NewExt = SubStr( '.CUT.CLO.DUT.DLO', Index, 4 )
  385.                             NewFile = Overlay( NewExt, File, Length( File ) - 4 )
  386.                             Delete( NewFile )
  387.                         END
  388.                     END
  389.                 END
  390.                 ELSE DO
  391.                     IF rtResult = 0 THEN DO
  392.                         /* Since this boss really should be skipped, we set
  393.                          * the "Polled" * flag, to prevent polling. This way
  394.                          * we remove the risk of getting several requesters
  395.                          * for the same node.*/
  396.                         Node.I.Polled = 1
  397.                     END
  398.  
  399.                     IF BossNum > 0 THEN DO
  400.                         Node.BossNum.ExtraPoll = 1
  401.                     END
  402.                     ELSE DO
  403.                         Nodes            = Nodes + 1
  404.                         I            = Nodes
  405.                         Node.I.0        = 1
  406.                         Node.I.1        = NodeNum
  407.                         Node.I.Boss        = ''
  408.                         Node.I.Days        = 0
  409.                         Node.I.Save        = 0
  410.                         Node.I.Poll        = StartDate - 100
  411.                         Node.I.Polled        = 0
  412.                         Node.I.Errors        = 0
  413.                         Node.I.ExtraPoll    = 0
  414.  
  415.                         IF Node.I.Password = '' THEN DO
  416.                             Node.I.Password  = NodePassword
  417.                         END
  418.                     END
  419.                 END
  420.             END
  421.         END
  422.     END
  423.  
  424. RETURN
  425.  
  426.  
  427. /* Set the defaults, and then read the configuration */
  428. ReadConfig:
  429.  
  430.     Nodes        = 0
  431.     Ignores        = 0
  432.     Akas        = 0
  433.     RexxName    = 'TrapDoor'
  434.     TrapDoorCmd    = 'TrapDoor'
  435.     PubScreen    = 'TrapDoor'
  436.     ConsoleName    = 'Con:0/14/640/100/Poll.rexx/SCREEN TrapDoor'
  437.     Outbound    = 'Mail:Outbound/'
  438.     RedialDelay    = 30
  439.     ErrorLimit    = 5
  440.     DoAsk        = 1
  441.     Crash        = 0
  442.     Direct        = 0
  443.     Normal        = 0
  444.     Request        = 0
  445.  
  446.     IF ~Open( 'Config', ConfigName, 'R' ) THEN DO
  447.         SAY 'Couldn''t open "'ConfigName'"'
  448.         RETURN( 0 )
  449.     END
  450.  
  451.     DO LineNum = 1 UNTIL Eof( 'Config' )
  452.         Line = ReadLn( 'Config' )
  453.  
  454.         IF Words( Line ) = 0 | SubStr( Line, 1, 1 ) = '#' THEN DO
  455.             ITERATE
  456.         END
  457.  
  458.         IF Words( Line ) < 2 THEN DO
  459.             SAY 'Missing argument on line 'LineNum' in "'ConfigName'"'
  460.             ITERATE
  461.         END
  462.  
  463.         /* Replace tabs with spaces, and do some argument parsing */
  464.         Line = Translate( Line, ' ', '09'x );
  465.         Cmd = Upper( Word( Line, 1 ) )
  466.         Args = SubStr( Line, WordIndex( Line, 2 ) )
  467.  
  468.         SELECT
  469.             WHEN Cmd = 'REXXNAME' THEN DO
  470.                 RexxName = Args
  471.             END
  472.             WHEN Cmd = 'TDCMD' THEN DO
  473.                 TrapDoorCmd = Args
  474.             END
  475.             WHEN Cmd = 'CONSOLE' THEN DO
  476.                 ConsoleName = Args
  477.             END
  478.             WHEN Cmd = 'OUTBOUND' THEN DO
  479.                 Outbound = Args
  480.                 LastChar = Right( Outbound, 1 )
  481.  
  482.                 IF LastChar ~= '/' & LastChar ~= ':' THEN DO
  483.                     Outbound = Outbound'/'
  484.                 END
  485.             END
  486.             WHEN Cmd = 'PUBSCREEN' THEN DO
  487.                 PubScreen = Args
  488.             END
  489.             WHEN Cmd = 'REDAILDELAY' | Cmd = 'REDIALDELAY' THEN DO
  490.                 IF ~DataType( Args, 'Numeric' ) THEN DO
  491.                     SAY 'Bad argument on line 'LineNum' in "'ConfigName'"'
  492.                 END
  493.                 ELSE DO
  494.                     RedialDelay = Args
  495.                 END
  496.             END
  497.             WHEN Cmd = 'ASK' THEN SELECT
  498.                 WHEN Args = 'YES' THEN DO
  499.                     DoAsk = 1
  500.                 END
  501.                 WHEN Args = 'NO' THEN DO
  502.                     DoAsk = 0
  503.                 END
  504.                 OTHERWISE DO
  505.                     SAY 'Bad argument on line 'LineNum' in "'ConfigName'"'
  506.                 END
  507.             END
  508.             WHEN Cmd = 'ERRORLIMIT' THEN DO
  509.                 ErrorLimit = Args
  510.             END
  511.             WHEN Cmd = 'IGNORE' THEN DO
  512.                 Ignores = Ignores + 1
  513.                 Ignore.Ignores = Args
  514.             END
  515.             WHEN Cmd = 'AKA' THEN DO
  516.                 IF Words( Args ) < 2 ) THEN DO
  517.                     SAY 'Not enough arguments on line 'LineNum' in "'ConfigName'"'
  518.                 END
  519.                 ELSE DO
  520.                     Akas = Akas + 1
  521.                     Aka.Akas.Node = Word( Args, 1 )
  522.                     Aka.Akas.Also = Word( Args, 2 )
  523.                 END
  524.             END
  525.             WHEN Cmd = 'POLL' THEN DO J = 1 FOR Words( Args )
  526.                 DoPoll = Word( Args, J )
  527.  
  528.                 SELECT
  529.                     WHEN DoPoll = 'CRASH' THEN DO    /* .CLO .CUT */
  530.                         Crash = 1
  531.                     END
  532.                     WHEN DoPoll = 'NOCRASH' THEN DO
  533.                         Crash = 0
  534.                     END
  535.                     WHEN DoPoll = 'DIRECT' THEN DO    /* .DLO .DUT */
  536.                         Direct = 1
  537.                     END
  538.                     WHEN DoPoll = 'NODIRECT' THEN DO
  539.                         Direct = 0
  540.                     END
  541.                     WHEN DoPoll = 'NORMAL' THEN DO    /* .FLO .OUT */
  542.                         Normal = 1
  543.                     END
  544.                     WHEN DoPoll = 'NONORMAL' THEN DO
  545.                         Normal = 0
  546.                     END
  547.                     WHEN DoPoll = 'REQUEST' THEN DO    /* .REQ */
  548.                         Request = 1
  549.                     END
  550.                     WHEN DoPoll = 'NOREQUEST' THEN DO
  551.                         Request = 0
  552.                     END
  553.                     OTHERWISE DO
  554.                         SAY 'Bad argument on line 'LineNum' in "'ConfigName'"'
  555.                     END
  556.                 END
  557.             END
  558.             WHEN Cmd = 'NODE' THEN DO
  559.                 /* Node stem usage:
  560.                  * Node.x.Boss        Nodenumber for current boss. Used if Node.x.y holds phonenumber
  561.                  * Node.x.Polled    If true, then this node have been polled (needed since the date _may_ change during script execution)
  562.                  * Node.x.0        Number of phonenumbers for current node.
  563.                  * Node.x.y        (Node.x.0 >= y >= 1) Various node/phone numbers
  564.                  * Node.x.Days        Days between pollings
  565.                  * Node.x.Save        This node's Node.x.Poll should be saved in Poll.data
  566.                  * Node.x.Password    Password for current boss
  567.                  * Node.x.Poll        Internal date of last polling
  568.                  * Node.x.ExtraPoll    True if a "non-sheduled" poll
  569.                  * Node.x.Errors    Number of (certain) errors for this node
  570.                  */
  571.                 Nodes = Nodes + 1
  572.                 I = Nodes
  573.                 Node.I.0        = Words( Args ) - 2
  574.                 Node.I.Poll        = StartDate - 100
  575.                 Node.I.Polled        = 0
  576.                 Node.I.Save        = 1
  577.                 Node.I.ExtraPoll    = 0
  578.                 Node.I.Password        = ''
  579.                 Node.I.Errors        = 0
  580.  
  581.                 IF Node.I.0 < 0 THEN DO
  582.                     SAY 'Argument(s) missing on line 'LineNum' in "'ConfigName'"'
  583.                 END
  584.                 ELSE DO
  585.                     Node.I.Days = Word( Args, 1 )
  586.                     Node.I.Boss = Word( Args, 2 )
  587.  
  588.                     IF Node.I.0 > 0 THEN DO J = 1 FOR Node.I.0
  589.                         Node.I.J = Word( Args, J + 2 )
  590.                     END
  591.                     ELSE DO
  592.                         Node.I.0 = 1
  593.                         Node.I.1 = Node.I.Boss
  594.                         Node.I.Boss = ''
  595.                     END
  596.  
  597.                     /* Take care of the password, if needed */
  598.                     IF Node.I.0 > 1 THEN DO
  599.                         J = Node.I.0
  600.  
  601.                         IF Left( Node.I.J, 3 ) = 'PW=' THEN DO
  602.                             Node.I.Password = SubStr( Node.I.J, 4 )
  603.                             Node.I.0 = Node.I.0 - 1
  604.                         END
  605.                         ELSE IF Show( 'Libraries', 'traplist.library' ) THEN DO
  606.                             NodePassword = FindNode( Node.I.Boss, 'Password' )
  607.  
  608.                             IF SubStr( NodePassword, 1, 1 ) = '1' THEN DO
  609.                                 Node.I.Password = SubStr( NodePassword, 3 )
  610.                             END
  611.                         END
  612.                     END
  613.                 END
  614.             END
  615.             OTHERWISE DO
  616.                 SAY 'Unknown configuration command on line 'LineNum' in "'ConfigName'"'
  617.             END
  618.         END
  619.     END
  620.  
  621.     CALL Close( 'Config' )
  622.  
  623. RETURN( 1 )
  624.  
  625.  
  626. /* Read the Poll.data file, containing the internal dates of the last
  627.  * successfull poll of the different nodes in the configuration file.
  628.  */
  629. ReadData:
  630.  
  631.     IF Open( 'Data', 'Mail:SmartPoll.data', 'R' ) THEN DO
  632.         DO I = 1 UNTIL Eof( 'Data' ) | I > Nodes
  633.             Line = ReadLn( 'Data' )
  634.  
  635.             IF DataType( Line, 'Numeric' ) THEN DO
  636.                 Node.I.Poll = Line
  637.                 Node.I.OrigPoll = Line
  638.             END
  639.         END
  640.  
  641.         CALL Close( 'Data' )
  642.     END
  643.  
  644. RETURN
  645.  
  646.  
  647. /* Start TrapDoor if needed. If we started it, set the TDStarted BOOL to TRUE */
  648. StartTD:
  649.  
  650.     IF ~Show( 'P', RexxName ) THEN DO
  651.         ADDRESS COMMAND
  652.  
  653.         'Run >Nil: 'TrapDoorCmd' REXXNAME 'RexxName' ANSWER'
  654.         'WaitForPort 'RexxName
  655.  
  656.         IF Show( 'P', RexxName ) THEN DO
  657.             TDStarted = 1
  658.         END
  659.         ELSE DO
  660.             SAY "Couldn't start TrapDoor"
  661.             RETURN( 0 )
  662.         END
  663.     END
  664.  
  665. RETURN( 1 )
  666.  
  667.  
  668. ERROR:
  669.     SAY '+++ Error 'RC' on line 'SIGL': 'ErrorText( RC )
  670.  
  671. HALT:
  672. BREAK_C:
  673.  
  674. SIGNAL SaveData
  675.